package commons.params.param_component;

import algo_lignes_sites.params.ParamsManager_ls;
import algo_lignes_sites.params.DlgParams_ls;
import commons.utils.Properties_INI;
import java.awt.Color;
import java.awt.Component;
import java.util.ArrayList;
import java.util.Properties;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;


public class ParamComponent_list_Select extends AbstractParamComponent implements ListSelectionListener {

	// La valeur de ce parametre consiste en la liste des item que l'utilisateur a sélectionné.
	// C'est cette sélection qui sera sauvegardee dans le fichier de paramétrage.
	private ArrayList<String> vSelection;

	private ArrayList<String> possibleValues;
	private JList jList;


	public ParamComponent_list_Select(String name, ParamsManager_ls paramsManager, JComponent component, boolean bCanBeNull) {
		super(name, paramsManager, component, bCanBeNull);
		assert component instanceof JList;
		vSelection = new ArrayList<String>();
		jList = (JList) component;
		jList.addListSelectionListener(this);
	}


	// Traitement des changement de sélection dans la liste
	public void valueChanged(ListSelectionEvent e) {
		if (e.getValueIsAdjusting()) return; // pas encore la vraie sélection ...

		//System.out.println("******* List selection **********");
		paramsManager.traiteOneModifUtilisateur();

	}
	// à initialiser avant tout appel à 'writeToComponent()'
	public void setPossibleValues (ArrayList<String> possibleValues) {
		this.possibleValues = possibleValues;
	}

	// Renvoi la liste des valeurs de vSelection qui ne sont pas dans possibleValues
	private ArrayList<String> getInvalidSelection() {
		ArrayList<String> vRes = new ArrayList<String>();
		for (String selectedItem : vSelection)
			if (!possibleValues.contains(selectedItem))
				vRes.add(selectedItem);
		return vRes;
	}

	//**************************************************************************
	//**************************************************************************


	public Object getValue() {
		return vSelection;
	}

	public void setValue(Object val) {
		if (val==null)
			this.vSelection = new ArrayList<String>();
		else {
			assert (val instanceof ArrayList);
			if ( ((ArrayList)val).size()>0 )
				assert (((ArrayList)val).get(0) instanceof String);
			this.vSelection = (ArrayList)val;
		}
		bIsNull = vSelection.size()==0;
	}

	public void writeToComponent() {
		assert (possibleValues != null);
		DefaultListModel listModel = new DefaultListModel();


		// Puis on ajoute toutes les valeurs permises
		for (String item : possibleValues)
			listModel.addElement(item);
		// On ajoute d'abord les élement sélectionnés mais pas dans les valeurs permises
		ArrayList<String> vInvalidSelection = getInvalidSelection();
		for (String item : vInvalidSelection)
			listModel.addElement(item);

		jList.setModel(listModel);

		// Un renderer spécial pour afficher en rouge la sélection invalide
		jList.setCellRenderer(new DefaultListCellRenderer()  {
			public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
				Component comp = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
				if (index>=possibleValues.size()) {
					comp.setBackground(DlgParams_ls.COLOR_INVALID);
					comp.setForeground(Color.WHITE);
				}
				return comp;
			}
		});

		// A présent on sélectionne dans la liste les éléments de vSelection
		for (String item : vSelection) {
			int indexOfItem = listModel.indexOf(item);
			jList.addSelectionInterval(indexOfItem, indexOfItem);
		}
	}

	public void readFromComponent() {
		vSelection.clear();
		// On récupère la sélection de la JList
		Object[] tabSelection = jList.getSelectedValues();
		for (Object item : tabSelection)
			vSelection.add((String)item);

		bIsNull = vSelection.isEmpty();
	}

	public void storeInProperties(Properties_INI props) {
		// On stocke d'abord le nombre d'éléments
		props.setProperty(name + ".nbValeur", ""+vSelection.size());
		// Puis les éléments eux-même
		int index=0;
		for (String item : vSelection)
			props.setProperty(name + ".valueNum_" + index++, item);
	}

	public boolean loadFromProperties(Properties_INI props) {
		vSelection.clear();
		bIsNull = true;

		// Lecture du nombre d'élément de la sélection
		if (!isThereProperty_int_pos(props, name + ".nbValeur"))
			return false;
		int nbField = readProperty_int(props, name + ".nbValeur");


		// Puis les éléments eux-même
		for (int i=0; i<nbField ; i++) {
			if (!isThereProperty(props, name + ".valueNum_" + i))
				return false;
			vSelection.add(readProperty(props, name + ".valueNum_" + i));
		}

		bIsNull = vSelection.isEmpty();
		return true;
	}

	public void makeStandardControls() {
		assert (possibleValues != null);

		// test nullité de la valeur
		if (!bCanBeNull && bIsNull && possibleValues.size()>0) {
			invalidateComponent("Paramètre obligatoire", true);
			return;
		}
		if (bCanBeNull && bIsNull) {
			return ;
		}

		// La sélection doit faire partie des valeurs possibles
		if (getInvalidSelection().size()>0) {
			invalidateComponent("Les valeurs sélectionnées en rouge ne font pas partie des valeurs sélectionnables. Les déselectionner.", true);
		}
	}


}
